#include <sys/time.h>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include "../../jerasure-2.h"
#include "../../reed_sol-2.h"
using namespace std;

int timeval_subtract (struct timeval *result, struct timeval *x, 
					  struct timeval *y);
int main( int argc, char** argv )
{
	int k, n, wpd;
	int packetsize, packetsperslice;
	int iterations;
	bool print;
	char* filename;

	JER_Slices *slices;
	JER_Matrix *jm;
	JER_Bitmatrix *jbm;
	clock_t start, stop;
	struct timeval time1, time2, result;
	FILE* fp;
	int i, j;
	vector<IVec> failures;

	if( argc != 8 && argc != 7 )
	{
		fprintf( stdout, "usage: encode_test n k wpd ps file iter [print]\n" );
		exit(0);
	}

	n = atoi( argv[1] );
	k = atoi( argv[2] );
	wpd = atoi( argv[3] );
	packetsize = atoi( argv[4] );
	packetsperslice = wpd;
	filename = argv[5];
	iterations = atoi( argv[6] );
	if( argc == 7 )
		print = false;
	else
		print = true;

	unsigned char buffer[n*packetsize*packetsperslice];

	jm = reed_sol_vandermonde_coding_matrix( k, n - k, wpd );
	jbm = new JER_Bitmatrix( *jm );
	slices = new JER_Slices();
	slices->K = k;
	slices->M = n - k;
	slices->W = wpd;
	slices->PS = packetsize;
	slices->size = packetsize * packetsperslice;
	fp = fopen( filename, "r" );
	fread( buffer, packetsize*packetsperslice, k, fp );
	fclose( fp );
	for( i = 0; i < n; i++ )
	{
		slices->ptrs.push_back( buffer + i * packetsize * packetsperslice );
	}
	for( i = 0; i < iterations; i++ )
	{
		failures.resize( i+1 );
		for( j = 0; j < n; j++ )
			failures[i].push_back( 0 );
		for( j = 0; j < n - k; j++ )
			failures[i][j] = k + ( lrand48() % (n-k) );
	}

	gettimeofday( &time1, NULL );
	//start = clock();
	for( i = 0; i < iterations; i++ )
	{
		JER_Bitmatrix_Encode( slices, jbm );	
	}
	//stop = clock();
	gettimeofday( &time2, NULL );
	timeval_subtract( &result, &time2, &time1 );
	if( print )
	fprintf( stdout, "Time elapsed = %us %uus\n", 
			 result.tv_sec, result.tv_usec);
	else
		fprintf( stdout, "%u.%06u\n", result.tv_sec, result.tv_usec );
}

int timeval_subtract (struct timeval *result, struct timeval *x, 
					  struct timeval *y)
{
	/* Perform the carry for the later subtraction by updating y. */
	if (x->tv_usec < y->tv_usec) {
		int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
		y->tv_usec -= 1000000 * nsec;
		y->tv_sec += nsec;
	}
	if (x->tv_usec - y->tv_usec > 1000000) {
		int nsec = (x->tv_usec - y->tv_usec) / 1000000;
		y->tv_usec += 1000000 * nsec;
		y->tv_sec -= nsec;
	}

	/* Compute the time remaining to wait.
	   tv_usec is certainly positive. */
	result->tv_sec = x->tv_sec - y->tv_sec;
	result->tv_usec = x->tv_usec - y->tv_usec;

	/* Return 1 if result is negative. */
	return x->tv_sec < y->tv_sec;
}
